#pragma

#include <iostream>
#include <memory>
#include "Epoller.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "log.hpp"
#include "Connection.hpp"
#include "IOService.hpp"
#include "Reactor.hpp"
#include "Protocol.hpp"
#include "calculator.hpp"

using namespace SocketModule;
using namespace LogModule;

// 连接模块
class Listener : public Connection
{
public:
    Listener(int port)
        : _listensock(std::make_unique<TcpSocket>()), _port(port)
    {
        _listensock->BuildTcpsocketMethood(_port);
        SetSockfd(_listensock->Fd());
        SetEvents(EPOLLIN | EPOLLET);
    }

    virtual void Sender() override
    {
    }
    virtual void Recever() override
    {
        // 读事件就绪
        // 获取新连接
        while (true)
        {
            InetAddr peer;
            int aerrno = 0;
            int sockfd = _listensock->accepter(&peer, &aerrno);
            if (sockfd > 0)
            {
                LOG(DEBUG, "accepter success : %d\n", sockfd);
                // 普通fd，处理IO，但也是Connection
                // 1. 设置sockfd为非阻塞
                // 2. 将sockfd包装成Connection
                auto conn = std::make_shared<IOService>(sockfd);
                conn->RegisterOnMessage(HandlerRequest);
                // 3. 插入EpollServer
                GetOwner()->InsertConnection(conn);
            }
            else
            {
                if (aerrno == EAGAIN || aerrno == EWOULDBLOCK)
                {
                    LOG(DEBUG, "accepter all connection ... done\n");
                    break;
                }
                else if (aerrno == EINTR)
                {
                    LOG(DEBUG, "accepter intr by signal, continue\n");
                    continue;
                }
                else
                {
                    LOG(WARNING, "accepter error ... Ihnore\n");
                    break;
                }
            }
        }
    }
    virtual void Excepter() override
    {
    }

    int Sockfd() { return _listensock->Fd(); }

    ~Listener()
    {
        _listensock->Close();
    }

private:
    std::unique_ptr<Socket> _listensock;
    int _port;
};